package com.onLineCar.driver.service.impl;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.onLineCar.DriverFeign;
import com.onLineCar.common.core.domain.Result;
import com.onLineCar.driver.domain.entity.*;
import com.onLineCar.driver.domain.entity.Request.*;
import com.onLineCar.driver.mapper.TDriverMapper;
import com.onLineCar.driver.service.ITDriverService;
import com.onLineCar.vehicle.entity.TblOrder;
import com.onLineCar.vehicle.entity.request.RequestUpdate;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 司机管理表 服务实现类
 * </p>
 *
 * @author dsr
 * @since 2023-12-12
 */
@Service
@Slf4j
public class TDriverServiceImpl extends ServiceImpl<TDriverMapper, TDriver> implements ITDriverService {

    @Autowired
    private TDriverMapper driverMapper;

    @Autowired
    private DriverFeign driverFeign;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private RedissonClient redissonClient;


    private static final Integer verifyCodeZero = 0;
    private static final Integer verifyCodeOne = 1;
    private static final Integer verifyCodeTwo = 2;
    private static final Integer verifyCodeThree = 3;
    private static final Integer verifyCodeFour = 4;
    private static final Integer verifyCodeFive = 5;
    private static final Integer verifyCodeTwoThree = 23;
    private static final Integer verifyCodeSeven = 7;
    private static final Integer verifyCodeNine = 9;
    private static final Integer verifyCodeSix = 6;
    // 节假日日期列表，格式为"月-日"
    private static final String[] HOLIDAYS = {
            "01-01", // 元旦
            "02-04", // 春节
            "02-05", // 春节
            "02-06", // 春节
            "04-04", // 清明节
            "05-01", // 劳动节
            "06-25", // 端午节
            "10-01", // 国庆节
            "10-02", // 国庆节
            "10-03"  // 国庆节
    };

    /**
     * 司机注册
     *
     * @param tDriver
     * @return
     */
    @Override
    public int registerDriver(TDriver tDriver) {
        tDriver.setCreateTime(new Date());
        tDriver.setUpdateTime(new Date());
        tDriver.setDriverEvaluate(verifyCodeZero);
        tDriver.setDriverState(verifyCodeZero);
        tDriver.setCheckState(verifyCodeZero);
        return driverMapper.insert(tDriver);
    }

    /**
     * 根据身份证号查询司机是否已注册
     *
     * @param queryWrapper
     * @return
     */
    @Override
    public TDriver queryDriverByIdCard(LambdaQueryWrapper<TDriver> queryWrapper) {

        TDriver tDriver = driverMapper.selectOne(queryWrapper);
        return tDriver;
    }

    /**
     * 根据审核状态查询司机集合
     *
     * @param reqCheck
     * @return
     */
    @Override
    public IPage<TDriver> queryDriverByState(ReqCheck reqCheck) {
        LambdaQueryWrapper<TDriver> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TDriver::getCheckState, verifyCodeZero);
        Page<TDriver> page = new Page<>(reqCheck.getPageNum(), reqCheck.getPageSize());
        return driverMapper.selectPage(page, queryWrapper);
    }

    /**
     * 根据Id查看司机详情 查询
     *
     * @param driverId
     * @return
     */
    @Override
    public TDriver queryDriverListByDriverId(Integer driverId) {
        return driverMapper.queryDriverListByDriverId(driverId);
    }

    /**
     * 审核司机
     *
     * @param requestDriver
     * @return
     */
    @Override
    public int updateDriverStateById(RequestDriver requestDriver) {
        int i = driverMapper.updateDriverStateById(requestDriver);
        if (requestDriver.getCheckState() == 3) {

        }
        return i;
    }


    /**
     * 版本号 乐观锁
     *
     * @param preemptOrder
     * @return
     */
    @Override
    public boolean preemptOrder(RequestPreempt preemptOrder) {
        LambdaQueryWrapper<TDriver> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(StringUtils.isNotBlank(preemptOrder.getDriverTell()), TDriver::getDriverTell, preemptOrder.getDriverTell());
        TDriver tDriver = driverMapper.selectOne(queryWrapper);
        Integer driverState = tDriver.getDriverState();
        if (!driverState.equals(verifyCodeFour)) {
            return false;
        }
        // 判断订单是否存在
        Preempt findByPreemptNumber = driverMapper.findByPreemptNumber(preemptOrder.getPreemptNumber());
        //不存在添加抢单表
        if (null != findByPreemptNumber) {
            return false;
        }
        // 设置抢单表状态为已被接单
        Result<TblOrder> data = driverFeign.selectOrderByNumber(preemptOrder.getPreemptNumber());
        TblOrder selectOrderByNumber = data.getData();

        Preempt preempt = new Preempt();
        if (data.getCode() != Result.FAIL) {
            preempt.setOrderNumber(preemptOrder.getPreemptNumber());
            preempt.setDriverTell(preemptOrder.getDriverTell());
            preempt.setUserId(Math.toIntExact(selectOrderByNumber.getPassengerInfoId()));
            preempt.setPreemptState(verifyCodeZero);
            preempt.setPreemptVersion(verifyCodeZero);
            driverMapper.insertPreempt(preempt);
        }
        int i = driverMapper.updateDriverState(preemptOrder.getDriverTell());
        System.out.println(i);
        if (i == verifyCodeZero) {
            return false;
        }
        RequestUpdate requestUpdate = new RequestUpdate();
        requestUpdate.setOrderNumber(preemptOrder.getPreemptNumber());
        requestUpdate.setDriverStatus(verifyCodeOne);
        Result result = driverFeign.updateOrderStateByOrderNumber(requestUpdate);
        if (result.getCode() == verifyCodeZero) {
            return false;
        }
        return true;
    }

    /**
     * 查询司机列表
     *
     * @return
     */
    @Override
    public List<TDriver> queryDriverList() {
        QueryWrapper<TDriver> wrapper = Wrappers.query();
        List<TDriver> queryDriverList = driverMapper.selectList(wrapper);
        return queryDriverList;
    }

    /**
     * 根据名称查询司机信息
     *
     * @param queryWrapper
     * @return
     */
    @Override
    public TDriver selectDriverByName(LambdaQueryWrapper<TDriver> queryWrapper) {
        TDriver selectDriverByName = driverMapper.selectOne(queryWrapper);
        return selectDriverByName;
    }

    /**
     * 根据订单计价
     *
     * @param requestValuation
     * @return
     */
    @Override
    public Valuation valuationOrderByNumber(RequestValuation requestValuation) {
        Valuation selectValuationByOrderNumber = driverMapper.selectValuationByOrderNumber(requestValuation.getOrderNumber());
        if (null != selectValuationByOrderNumber) {
            log.info("订单已经存在,直接返回订单结果");   //订单编号        接到乘客时间             总路程  乘客下车时间             车辆级别
            return selectValuationByOrderNumber;     //OrderNumber    ReceivePassengerTime   SumKm  PassengerGetoffTime     VehicleLevel
        }                                            //过路费                   总金额
        log.info("订单不存在,开始计算订单价值");         //ValuationTollPrice      ValuationSumPrice
        //查询订单信息
        Result<TblOrder> tblOrderResult = driverFeign.selectOrderByNumber(requestValuation.getOrderNumber());
        TblOrder data = tblOrderResult.getData();
        Valuation valuation = new Valuation();
        //判断下单时间是否为高峰期,高峰期加价20%//receive_passenger_time
        Date startTime = data.getReceivePassengerTime();
        String pattern = "HH";
        Locale locale = Locale.getDefault();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern, locale);
        String time = simpleDateFormat.format(startTime);
        int hour = Integer.parseInt(time);
        //判断下单时间是否为高峰期,高峰期加价20%
        if (verifyCodeSeven <= hour && verifyCodeNine >= hour) {
            valuation.setValuationSpecial(new BigDecimal(2.4));
        } else {
            valuation.setValuationSpecial(BigDecimal.ZERO);
        }
        //是否为夜间
        if (verifyCodeTwoThree <= hour && verifyCodeFive >= hour) {
            valuation.setValuationNight(new BigDecimal(6.0));
        } else {
            valuation.setValuationNight(BigDecimal.ZERO);
        }
        //判断是否为节假日
        SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd");
        String today = dateFormat.format(startTime);
        for (String holiday : HOLIDAYS) {
            if (holiday.equals(today)) {
                valuation.setValuationSpecial(new BigDecimal(2.4));
            } else {
                valuation.setValuationSpecial(BigDecimal.ZERO);
            }
        }
        //起步价12元
        valuation.setValuationBeginPrice(new BigDecimal(12.0));
        //总路程价格
        Integer sumKm = data.getSumKm();
        int newKm = sumKm - verifyCodeTwo;
        if (newKm > verifyCodeZero) {
            valuation.setValuationKmPrice(new BigDecimal(newKm * 2.5));
        } else {
            valuation.setValuationKmPrice(BigDecimal.ZERO);
        }
        //时间价钱
        Date passengerGetoffTime = data.getPassengerGetoffTime();
        long time1 = passengerGetoffTime.getTime();
        long time2 = startTime.getTime();
        long l = time1 - time2;
        //分钟数 = (毫秒值 / 1000) / 60
        double l1 = (double) l / 1000 / 60;
        //每分钟0.3元
        valuation.setValuationTimePrice(new BigDecimal(l1 * 0.3));
        //车辆级别价格
        Integer vehicleLevel = data.getVehicleLevel();
        if (verifyCodeOne.equals(vehicleLevel)) {
            //豪华车
            valuation.setValuationCarType(new BigDecimal(200));
        }
        if (verifyCodeTwo.equals(vehicleLevel)) {
            //品牌车
            valuation.setValuationCarType(new BigDecimal(50));
        }
        if (verifyCodeThree.equals(vehicleLevel)) {
            //越野车
            valuation.setValuationCarType(new BigDecimal(30));
        }
        if (verifyCodeFour.equals(vehicleLevel)) {
            //普通车
            valuation.setValuationCarType(BigDecimal.ZERO);
        }
        //添加过路费
        valuation.setValuationTollPrice(requestValuation.getValuationTollPrice());
        //添加总金额
        valuation.setValuationSumPrice(
                valuation.getValuationBeginPrice()
                        .add(valuation.getValuationKmPrice())
                        .add(valuation.getValuationTimePrice())
                        .add(valuation.getValuationCarType())
                        .add(valuation.getValuationSpecial())
                        .add(valuation.getValuationNight())
                        .add(valuation.getValuationTollPrice()));
        //订单编号
        valuation.setOrderNumber(requestValuation.getOrderNumber());
        driverMapper.insertValuation(valuation);
        return valuation;
    }

    /**
     * 根据车牌号查询司机信息
     */
    @Override
    public TDriver selectDriverByCarId(List<String> carId) {
        return driverMapper.selectDriverByCarId(carId);
    }

    /**
     * redis分布式锁
     *
     * @param reqDriverPreemptOrder
     * @return
     */
    @Override
    public boolean driverPreemptOrder(ReqDriverPreemptOrder reqDriverPreemptOrder) {
        // 构造分布式锁的key
        String lockKey = "order_lock_" + reqDriverPreemptOrder.getOrderNumber();
        // 生成一个唯一的value
        String lockValue = UUID.randomUUID().toString();
        Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, 30, TimeUnit.MINUTES);
        if (locked != null && locked) {
            try {
                // 改状态
                return true;
            } finally {
                // 释放锁
                Object currentValue = redisTemplate.opsForValue().get(lockKey);
                if (lockValue.equals(currentValue)) {
                    redisTemplate.delete(lockKey);
                }
            }
        } else {
            // 未获取到锁，说明抢单失败
            return false;
        }
    }

    /**
     * redisson分布式锁
     *
     * @param reqDriverPreemptOrder
     * @return
     */
    @Override
    public boolean redissonDriverPreempt(ReqDriverPreemptOrder reqDriverPreemptOrder) {
        String lockKey = "order_lock_" + reqDriverPreemptOrder.getOrderNumber();
        RLock lock = redissonClient.getLock(lockKey);
        try {
            // 尝试获取锁，等待时间为3秒，持有锁的时间为5秒
            if (lock.tryLock(3, 5, TimeUnit.SECONDS)) {
                // 获取到锁，执行抢单逻辑
                return true;
            } else {
                // 未获取到锁，抢单失败
                return false;
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        } finally {
            lock.unlock();
        }
    }

    /**
     * 查询钱包信息
     *
     * @param walletId
     * @return
     */
    @Override
    public List<Wallet> selectWalletInfo(Integer walletId) {
        return driverMapper.selectWalletInfo(walletId);
    }

    /**
     * 查询钱包对应优惠券
     *
     * @param walletId
     * @return
     */
    @Override
    public List<Discount> selectDiscountInfo(Integer walletId) {
        return driverMapper.selectDiscountInfo(walletId);
    }

    @Override
    public void insertWallet(Wallet wallet) {
        driverMapper.insertWallet(wallet);
    }

    @Override
    public void insertWalletPrice(ReqWallet reqWallet) {
        driverMapper.insertWalletPrice(reqWallet);
    }

    @Override
    public String WalletPayMoney(WalletPay walletPay) {
        Wallet selectWallet =driverMapper.selectWallet(walletPay.getUserId(),walletPay.getPwd());
        //密码输入错误
        if (selectWallet==null){
            return "密码输入错误";
        }
        BigDecimal walletBalance = selectWallet.getWalletBalance();
        System.out.println(walletBalance);
        int i = walletBalance.compareTo(walletPay.getWalletPrice());
        //钱包余额小于支付余额
        if (i<verifyCodeZero){
            return "余额不足";
        }
        //钱包余额减支付余额
        driverMapper.subtractWalletPrice(walletPay.getUserId(),walletPay.getWalletPrice());
        RequestUpdate requestUpdate = new RequestUpdate();
        requestUpdate.setOrderNumber(walletPay.getOrderNumber());
        requestUpdate.setDriverStatus(verifyCodeSix);
        driverFeign.updateUserReach(requestUpdate);
        return "支付成功";
    }


//    @Override
//    public List<Discount> selectDiscountInfo(Insert walletId) {
//        return driverMapper.selectDiscountInfo(walletId);
//    }
}
